<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="Hugo 0.98.0" />

  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="author" content="" />
  <meta property="og:url" content="/posts/%E7%A4%BE%E5%8C%BA%E4%B9%A6%E7%B1%8D/c%E8%AF%AD%E8%A8%80%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97/%E5%85%A5%E9%97%A8%E6%8C%87%E9%92%88/" />
  <link rel="canonical" href="/posts/%E7%A4%BE%E5%8C%BA%E4%B9%A6%E7%B1%8D/c%E8%AF%AD%E8%A8%80%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97/%E5%85%A5%E9%97%A8%E6%8C%87%E9%92%88/" /><link rel="alternate" type="application/atom+xml" href="/index.xml" title="信息管理实验室">

  <script type="application/ld+json">
  {
      "@context" : "http://schema.org",
      "@type" : "BlogPosting",
      "mainEntityOfPage": {
           "@type": "WebPage",
           "@id": "\/"
      },
      "articleSection" : "posts",
      "name" : "入门：指针",
      "headline" : "入门：指针",
      "description" : "指针的本质是内存地址，其灵活之处在于\n 可以根据数据的增减，审时度势地调整数据地储存空间（动态内存分配） 参照数据的性质，方便迅速地转换数据的解析方式（数据类型转换）  学习一项技术最好的方式，就是动手实践，下面我们将从取址运算入手，启动指针的学习。\n\/* scanf_error.c Show a error case BeginnerC *\/ #include \u0026lt;stdio.h\u0026gt;int main() {  int number;  scanf(\u0026#34;%d\u0026#34;, number);  return 0; } 让我们回顾一个经典的错误。\n在这个案例中，我们在为 scanf 函数提供参数的时候，没有使用 \u0026amp; 运算提取 number 的地址，而是直接传入。\n由于 number 并没有初始化，因此它实际上就是一个随机值，这会引发一个内存读写错误，如图所示。\n解决的办法，往往也相当简单，就是提供出相关的地址，而在这里，我们采用指针方式解决。\n\/* scanf_right.c Use the point to the scanf BeginnerC *\/ #include \u0026lt;stdio.h\u0026gt;int main() {  int number;  int *p = \u0026amp;number;  scanf(\u0026#34;%d\u0026#34;, p);  printf(\u0026#34;%d %d\\n\u0026#34;, number, *p);  return 0; } 在这个案例之中，我们首次使用指针，如您所见，指针的语法实际上非常简单",
      "inLanguage" : "en-US",
      "author" : "",
      "creator" : "",
      "publisher": "",
      "accountablePerson" : "",
      "copyrightHolder" : "",
      "copyrightYear" : "2023",
      "datePublished": "2023-01-30 00:00:00 \u002b0000 UTC",
      "dateModified" : "2023-01-30 00:00:00 \u002b0000 UTC",
      "url" : "\/posts\/%E7%A4%BE%E5%8C%BA%E4%B9%A6%E7%B1%8D\/c%E8%AF%AD%E8%A8%80%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97\/%E5%85%A5%E9%97%A8%E6%8C%87%E9%92%88\/",
      "keywords" : [ "C语言入门指南","C语言","信息管理实验室", ]
  }
</script>
<title>入门：指针</title>
  <meta property="og:title" content="入门：指针" />
  <meta property="og:type" content="article" />
  <meta property="og:description" content="指针的本质是内存地址，其灵活之处在于
 可以根据数据的增减，审时度势地调整数据地储存空间（动态内存分配） 参照数据的性质，方便迅速地转换数据的解析方式（数据类型转换）  学习一项技术最好的方式，就是动手实践，下面我们将从取址运算入手，启动指针的学习。
/* scanf_error.c Show a error case BeginnerC */ #include &amp;lt;stdio.h&amp;gt;int main() {  int number;  scanf(&amp;#34;%d&amp;#34;, number);  return 0; } 让我们回顾一个经典的错误。
在这个案例中，我们在为 scanf 函数提供参数的时候，没有使用 &amp;amp; 运算提取 number 的地址，而是直接传入。
由于 number 并没有初始化，因此它实际上就是一个随机值，这会引发一个内存读写错误，如图所示。
解决的办法，往往也相当简单，就是提供出相关的地址，而在这里，我们采用指针方式解决。
/* scanf_right.c Use the point to the scanf BeginnerC */ #include &amp;lt;stdio.h&amp;gt;int main() {  int number;  int *p = &amp;amp;number;  scanf(&amp;#34;%d&amp;#34;, p);  printf(&amp;#34;%d %d\n&amp;#34;, number, *p);  return 0; } 在这个案例之中，我们首次使用指针，如您所见，指针的语法实际上非常简单" />
  <meta name="description" content="指针的本质是内存地址，其灵活之处在于
 可以根据数据的增减，审时度势地调整数据地储存空间（动态内存分配） 参照数据的性质，方便迅速地转换数据的解析方式（数据类型转换）  学习一项技术最好的方式，就是动手实践，下面我们将从取址运算入手，启动指针的学习。
/* scanf_error.c Show a error case BeginnerC */ #include &amp;lt;stdio.h&amp;gt;int main() {  int number;  scanf(&amp;#34;%d&amp;#34;, number);  return 0; } 让我们回顾一个经典的错误。
在这个案例中，我们在为 scanf 函数提供参数的时候，没有使用 &amp;amp; 运算提取 number 的地址，而是直接传入。
由于 number 并没有初始化，因此它实际上就是一个随机值，这会引发一个内存读写错误，如图所示。
解决的办法，往往也相当简单，就是提供出相关的地址，而在这里，我们采用指针方式解决。
/* scanf_right.c Use the point to the scanf BeginnerC */ #include &amp;lt;stdio.h&amp;gt;int main() {  int number;  int *p = &amp;amp;number;  scanf(&amp;#34;%d&amp;#34;, p);  printf(&amp;#34;%d %d\n&amp;#34;, number, *p);  return 0; } 在这个案例之中，我们首次使用指针，如您所见，指针的语法实际上非常简单" />
  <meta property="og:locale" content="zh-cn" /><meta property="og:image" content="" />
  

  
    <style>body{font-family:bree serif,sans-serif;-webkit-font-smoothing:antialiased;margin:0 20px}article{max-width:800px;margin-left:auto;margin-right:auto}a{color:#000;text-decoration:none}a:hover{font-weight:600;text-decoration:underline}.post-ads{margin:50px 0}.markdown-body{font-size:18px;max-width:100%}.markdown-body a{text-decoration:underline;text-decoration-color:#000}.markdown-body blockquote{margin:0;padding:0 1em;color:#57606a;border-left:.25em solid #d0d7de}.markdown-body pre{padding:16px;overflow:auto;border-radius:10px}.markdown-body code{padding:.2em .4em;font-size:85%;background-color:#f6f8fa;border-radius:6px}.markdown-body pre>code{padding:0;font-size:100%;background-color:inherit;border:0}.Chinese .markdown-body{line-height:200%}.site-date-catalog{font-size:2rem}.header-title{font-size:2rem;font-weight:700;margin-top:32px;font-family:bungee shade,sans-serif}.header-title a{text-decoration:none}.header-subtitle{color:#666}.header-items{margin:10px 0}.header-item{margin:0 5px}.header-line{width:100%;border-width:2px;border-color:#482936;border-style:solid none none none}.lang-switch{font-weight:600}#posts-list{min-height:600px}.posts-line{font-size:1.2rem;margin:12px 0}.posts-categories{font-size:.8rem;margin:auto;text-align:center}.posts-category{padding:3px 0;border:#000 2px solid;border-radius:5px}.site-footer{margin-top:50px}.site-footer-item{margin-right:12px}.post-content img{max-width:100%;display:block;margin-right:auto;margin-top:12px}.post-header{margin-bottom:50px}.post-title{font-size:2rem;font-weight:600}.post-tags{display:inline-block;font-weight:600;padding:2px 5px;margin-right:6px;margin-top:4px;border:#000 2px solid;border-radius:5px}.post-date{font-weight:800;font-style:italic}.post-author{float:right;font-weight:600}.page-content{min-height:60%}.post-content{margin-bottom:50px}.post-content p{hyphens:auto;line-height:1.8;text-justify:ideographic;margin-bottom:1em}.related-content{border-width:3px;border-style:solid;border-color:#000;padding:0 10px;margin-bottom:50px;margin-top:100px}.related-content li{margin:5px 0}.taxonomy-term{font-size:3rem}.gallery-img{text-align:center}.gallery-img span{text-align:center}.gallery-img-desc{font-size:.8em;font-weight:800}@media screen and (max-width:600px){.header-title,.header-subtitle,.header-items{text-align:center}.posts-line{font-size:16px}.markdown-body{font-size:16px}.post-title{font-size:2rem}.post-content p{letter-spacing:.05em}}@media screen and (max-width:48em){.posts-category{display:none}}</style>
  
  
    <style>.container,.container-fluid{margin-right:auto;margin-left:auto}.container-fluid{padding-right:2rem;padding-left:2rem}.row{box-sizing:border-box;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 1 auto;flex:initial;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-.5rem;margin-left:-.5rem}.row.reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.col.reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}.col-xs,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-offset-0,.col-xs-offset-1,.col-xs-offset-10,.col-xs-offset-11,.col-xs-offset-12,.col-xs-offset-2,.col-xs-offset-3,.col-xs-offset-4,.col-xs-offset-5,.col-xs-offset-6,.col-xs-offset-7,.col-xs-offset-8,.col-xs-offset-9{box-sizing:border-box;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:none;padding-right:.5rem;padding-left:.5rem}.col-xs{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;max-width:100%}.col-xs-1{-ms-flex-preferred-size:8.33333333%;flex-basis:8.33333333%;max-width:8.33333333%}.col-xs-2{-ms-flex-preferred-size:16.66666667%;flex-basis:16.66666667%;max-width:16.66666667%}.col-xs-3{-ms-flex-preferred-size:25%;flex-basis:25%;max-width:25%}.col-xs-4{-ms-flex-preferred-size:33.33333333%;flex-basis:33.33333333%;max-width:33.33333333%}.col-xs-5{-ms-flex-preferred-size:41.66666667%;flex-basis:41.66666667%;max-width:41.66666667%}.col-xs-6{-ms-flex-preferred-size:50%;flex-basis:50%;max-width:50%}.col-xs-7{-ms-flex-preferred-size:58.33333333%;flex-basis:58.33333333%;max-width:58.33333333%}.col-xs-8{-ms-flex-preferred-size:66.66666667%;flex-basis:66.66666667%;max-width:66.66666667%}.col-xs-9{-ms-flex-preferred-size:75%;flex-basis:75%;max-width:75%}.col-xs-10{-ms-flex-preferred-size:83.33333333%;flex-basis:83.33333333%;max-width:83.33333333%}.col-xs-11{-ms-flex-preferred-size:91.66666667%;flex-basis:91.66666667%;max-width:91.66666667%}.col-xs-12{-ms-flex-preferred-size:100%;flex-basis:100%;max-width:100%}.col-xs-offset-0{margin-left:0}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-11{margin-left:91.66666667%}.start-xs{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;text-align:start}.center-xs{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center}.end-xs{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;text-align:end}.top-xs{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.middle-xs{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.bottom-xs{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.around-xs{-ms-flex-pack:distribute;justify-content:space-around}.between-xs{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.first-xs{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.last-xs{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}@media only screen and (min-width:48em){.container{width:49rem}.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-offset-0,.col-sm-offset-1,.col-sm-offset-10,.col-sm-offset-11,.col-sm-offset-12,.col-sm-offset-2,.col-sm-offset-3,.col-sm-offset-4,.col-sm-offset-5,.col-sm-offset-6,.col-sm-offset-7,.col-sm-offset-8,.col-sm-offset-9{box-sizing:border-box;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:none;padding-right:.5rem;padding-left:.5rem}.col-sm{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;max-width:100%}.col-sm-1{-ms-flex-preferred-size:8.33333333%;flex-basis:8.33333333%;max-width:8.33333333%}.col-sm-2{-ms-flex-preferred-size:16.66666667%;flex-basis:16.66666667%;max-width:16.66666667%}.col-sm-3{-ms-flex-preferred-size:25%;flex-basis:25%;max-width:25%}.col-sm-4{-ms-flex-preferred-size:33.33333333%;flex-basis:33.33333333%;max-width:33.33333333%}.col-sm-5{-ms-flex-preferred-size:41.66666667%;flex-basis:41.66666667%;max-width:41.66666667%}.col-sm-6{-ms-flex-preferred-size:50%;flex-basis:50%;max-width:50%}.col-sm-7{-ms-flex-preferred-size:58.33333333%;flex-basis:58.33333333%;max-width:58.33333333%}.col-sm-8{-ms-flex-preferred-size:66.66666667%;flex-basis:66.66666667%;max-width:66.66666667%}.col-sm-9{-ms-flex-preferred-size:75%;flex-basis:75%;max-width:75%}.col-sm-10{-ms-flex-preferred-size:83.33333333%;flex-basis:83.33333333%;max-width:83.33333333%}.col-sm-11{-ms-flex-preferred-size:91.66666667%;flex-basis:91.66666667%;max-width:91.66666667%}.col-sm-12{-ms-flex-preferred-size:100%;flex-basis:100%;max-width:100%}.col-sm-offset-0{margin-left:0}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-11{margin-left:91.66666667%}.start-sm{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;text-align:start}.center-sm{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center}.end-sm{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;text-align:end}.top-sm{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.middle-sm{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.bottom-sm{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.around-sm{-ms-flex-pack:distribute;justify-content:space-around}.between-sm{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.first-sm{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.last-sm{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}}@media only screen and (min-width:64em){.container{width:65rem}.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-offset-0,.col-md-offset-1,.col-md-offset-10,.col-md-offset-11,.col-md-offset-12,.col-md-offset-2,.col-md-offset-3,.col-md-offset-4,.col-md-offset-5,.col-md-offset-6,.col-md-offset-7,.col-md-offset-8,.col-md-offset-9{box-sizing:border-box;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:none;padding-right:.5rem;padding-left:.5rem}.col-md{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;max-width:100%}.col-md-1{-ms-flex-preferred-size:8.33333333%;flex-basis:8.33333333%;max-width:8.33333333%}.col-md-2{-ms-flex-preferred-size:16.66666667%;flex-basis:16.66666667%;max-width:16.66666667%}.col-md-3{-ms-flex-preferred-size:25%;flex-basis:25%;max-width:25%}.col-md-4{-ms-flex-preferred-size:33.33333333%;flex-basis:33.33333333%;max-width:33.33333333%}.col-md-5{-ms-flex-preferred-size:41.66666667%;flex-basis:41.66666667%;max-width:41.66666667%}.col-md-6{-ms-flex-preferred-size:50%;flex-basis:50%;max-width:50%}.col-md-7{-ms-flex-preferred-size:58.33333333%;flex-basis:58.33333333%;max-width:58.33333333%}.col-md-8{-ms-flex-preferred-size:66.66666667%;flex-basis:66.66666667%;max-width:66.66666667%}.col-md-9{-ms-flex-preferred-size:75%;flex-basis:75%;max-width:75%}.col-md-10{-ms-flex-preferred-size:83.33333333%;flex-basis:83.33333333%;max-width:83.33333333%}.col-md-11{-ms-flex-preferred-size:91.66666667%;flex-basis:91.66666667%;max-width:91.66666667%}.col-md-12{-ms-flex-preferred-size:100%;flex-basis:100%;max-width:100%}.col-md-offset-0{margin-left:0}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-3{margin-left:25%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-6{margin-left:50%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-9{margin-left:75%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-11{margin-left:91.66666667%}.start-md{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;text-align:start}.center-md{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center}.end-md{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;text-align:end}.top-md{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.middle-md{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.bottom-md{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.around-md{-ms-flex-pack:distribute;justify-content:space-around}.between-md{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.first-md{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.last-md{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}}@media only screen and (min-width:75em){.container{width:76rem}.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-offset-0,.col-lg-offset-1,.col-lg-offset-10,.col-lg-offset-11,.col-lg-offset-12,.col-lg-offset-2,.col-lg-offset-3,.col-lg-offset-4,.col-lg-offset-5,.col-lg-offset-6,.col-lg-offset-7,.col-lg-offset-8,.col-lg-offset-9{box-sizing:border-box;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:none;padding-right:.5rem;padding-left:.5rem}.col-lg{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;max-width:100%}.col-lg-1{-ms-flex-preferred-size:8.33333333%;flex-basis:8.33333333%;max-width:8.33333333%}.col-lg-2{-ms-flex-preferred-size:16.66666667%;flex-basis:16.66666667%;max-width:16.66666667%}.col-lg-3{-ms-flex-preferred-size:25%;flex-basis:25%;max-width:25%}.col-lg-4{-ms-flex-preferred-size:33.33333333%;flex-basis:33.33333333%;max-width:33.33333333%}.col-lg-5{-ms-flex-preferred-size:41.66666667%;flex-basis:41.66666667%;max-width:41.66666667%}.col-lg-6{-ms-flex-preferred-size:50%;flex-basis:50%;max-width:50%}.col-lg-7{-ms-flex-preferred-size:58.33333333%;flex-basis:58.33333333%;max-width:58.33333333%}.col-lg-8{-ms-flex-preferred-size:66.66666667%;flex-basis:66.66666667%;max-width:66.66666667%}.col-lg-9{-ms-flex-preferred-size:75%;flex-basis:75%;max-width:75%}.col-lg-10{-ms-flex-preferred-size:83.33333333%;flex-basis:83.33333333%;max-width:83.33333333%}.col-lg-11{-ms-flex-preferred-size:91.66666667%;flex-basis:91.66666667%;max-width:91.66666667%}.col-lg-12{-ms-flex-preferred-size:100%;flex-basis:100%;max-width:100%}.col-lg-offset-0{margin-left:0}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-11{margin-left:91.66666667%}.start-lg{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;text-align:start}.center-lg{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center}.end-lg{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;text-align:end}.top-lg{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.middle-lg{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.bottom-lg{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.around-lg{-ms-flex-pack:distribute;justify-content:space-around}.between-lg{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.first-lg{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.last-lg{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}}</style>
  

  

  <link href="/index.xml" rel="alternate" type="application/rss+xml"
    title="信息管理实验室">
  
  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css?family=Bree+Serif|Bungee+Shade" rel="stylesheet">
  
  

  
  
</head>


<body>
  <article class="post " id="article">
    <div class="row">
      <div class="col-xs-12">
        <div class="site-header">
          
<header>
  <div class="header-title">
    <a href="/"
      >信息管理实验室</a
    >
  </div>
  <div class="header-subtitle"></div>
</header>
<div class="row end-md center-xs header-items">
  
  <div class="header-item">
    <a href="/posts/%e4%bd%a0%e5%a5%bd%e6%9c%8b%e5%8f%8b/" target="_blank">About</a>
  </div>
  
  <div class="header-item">
    <a href="/tags/%e6%88%91%e4%bb%ac%e7%9a%84%e4%bc%99%e4%bc%b4/" target="_blank">Friends</a>
  </div>
  
  <div class="header-item">
    <a href="/tags/%e7%a4%be%e5%8c%ba%e4%b9%a6%e7%b1%8d/" target="_blank">Books</a>
  </div>
  
</div>
<div class="row end-xs">
   
</div>
<div class="header-line"></div>

        </div>
        <header class="post-header">
          <h1 class="post-title">入门：指针</h1>
          
          <div class="row post-desc">
            <div class="col-xs-6">
              
              <time class="post-date">
                2023-01-30
              </time>
              
              
              
              <a href="/series/c%e8%af%ad%e8%a8%80%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/"><strong>&nbsp;《C语言入门指南》</strong></a>
              
              
              <br>
            </div>
          </div>
          <div class="row end-xs">
            
              <a href="/author/%e6%95%ac%e7%ab%a0/"><strong>&nbsp;@敬章</strong></a>        
            
          </div>
          
        </header>

        <div class="post-content markdown-body">
          
          <p><strong>指针的本质是内存地址</strong>，其灵活之处在于</p>
<ul>
<li>可以根据数据的增减，审时度势地调整数据地储存空间（动态内存分配）</li>
<li>参照数据的性质，方便迅速地转换数据的解析方式（数据类型转换）</li>
</ul>
<p>学习一项技术最好的方式，就是动手实践，下面我们将从取址运算入手，启动指针的学习。</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673229288861.png" alt="1673229288861"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    scanf_error.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Show a error case
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> number;
</span></span><span style="display:flex;"><span>    scanf(<span style="color:#e6db74">&#34;%d&#34;</span>, number);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>让我们回顾一个经典的错误。</p>
<p>在这个案例中，我们在为 scanf 函数提供参数的时候，没有使用 <code>&amp;</code> 运算提取 <code>number</code> 的地址，而是直接传入。</p>
<p>由于 number 并没有初始化，因此它实际上就是一个随机值，这会引发一个内存读写错误，如图所示。</p>
<p>解决的办法，往往也相当简单，就是提供出相关的地址，而在这里，我们采用指针方式解决。</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673229707762.png" alt="1673229707762"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    scanf_right.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Use the point to the scanf
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> number;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>p <span style="color:#f92672">=</span> <span style="color:#f92672">&amp;</span>number;
</span></span><span style="display:flex;"><span>    scanf(<span style="color:#e6db74">&#34;%d&#34;</span>, p);
</span></span><span style="display:flex;"><span>    printf(<span style="color:#e6db74">&#34;%d %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, number, <span style="color:#f92672">*</span>p);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>在这个案例之中，我们首次使用指针，如您所见，指针的语法实际上非常简单</p>
<p><code>type *var_name;</code></p>
<p>其中，* 就代表了变量的含义（指针），而 type 则代表了数据的解析方式。</p>
<p>而在之后的 scanf 中，我们将 变量p 中储存的 内存地址进行传入，从而实现了数据的读写。</p>
<p>在最后，我们打印 number 与 *p 的值，在这里，我们指出：</p>
<ol>
<li>number 就代表 number 本身的数值，其含义就是 <code>*(&amp;number)</code> ，此处 * 运算的意思表示：<strong>提取对应内存地址的数据</strong></li>
<li>*p 表示，提取 p 储存的内存地址的数值，因为 <code>p = &amp;number</code> ，所以它等价于 <code>number</code></li>
</ol>
<p>回顾 C语言 中的数据类型，我们发现，数据类型的核心，就是对二进制数据设定合理的布局方式与解析方式。</p>
<p>而我们的变量，则根据自身的数据类型，对自身所处的内存逻辑地址进行读写。</p>
<p>以数组为例，在之前我们的分析中，我们都知道，数组是同一类型元素的集合，用于连续地存取数据。</p>
<p>而现在，我们可以以内存视角分析数组：<strong>数组就是一片连续的内存区域</strong></p>
<p><img src="image/%E6%8C%87%E9%92%88/1673255830915.png" alt="1673255830915"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    array_memory.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Show the array&#39;s essence
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">PrintNumberList</span>(<span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>array, <span style="color:#66d9ef">int</span> count)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;i <span style="color:#f92672">&lt;</span> count;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;%d &#34;</span>, <span style="color:#f92672">*</span>(array <span style="color:#f92672">+</span> i));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    puts(<span style="color:#e6db74">&#34;&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">GenerateNumberList</span>(<span style="color:#66d9ef">int</span> array[], <span style="color:#66d9ef">int</span> count)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;i <span style="color:#f92672">&lt;</span> count;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        array[i] <span style="color:#f92672">=</span> i;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> number_list[<span style="color:#ae81ff">10</span>] <span style="color:#f92672">=</span> {};
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> number_list_backup[<span style="color:#ae81ff">10</span>] <span style="color:#f92672">=</span> {};
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">double</span> <span style="color:#f92672">*</span>p <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> count_memory <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    GenerateNumberList(number_list, <span style="color:#ae81ff">10</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (p <span style="color:#f92672">=</span> (<span style="color:#66d9ef">double</span><span style="color:#f92672">*</span>)(<span style="color:#66d9ef">void</span><span style="color:#f92672">*</span>)number_list;count_memory <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">sizeof</span>(number_list);p<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">*</span>(<span style="color:#66d9ef">double</span><span style="color:#f92672">*</span>)(<span style="color:#66d9ef">void</span><span style="color:#f92672">*</span>)((<span style="color:#66d9ef">char</span><span style="color:#f92672">*</span>)(<span style="color:#66d9ef">void</span><span style="color:#f92672">*</span>)number_list_backup <span style="color:#f92672">+</span> count_memory) <span style="color:#f92672">=</span> <span style="color:#f92672">*</span>p;
</span></span><span style="display:flex;"><span>        count_memory <span style="color:#f92672">+=</span> <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">double</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    PrintNumberList(number_list_backup, <span style="color:#ae81ff">10</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>这是一个非常绕的例子，但是它很好地说明了许多重要的问题。</p>
<p>我们逐步展开分析。</p>
<p>首先是 PrintNumberList 与 GenerateNumberList 两个函数，他们的意义显而易见，打印数组的值与为数组生成数据。</p>
<p>值得注意的是，它体现出 array[] 等价于 <code>array</code>，事实上，数组名就是数组首地址的开端，所以在这个意义上来看，数组就是指针（都是内存地址）。</p>
<p>其次，我们让一个 double 类型的指针 p 指向了 int 类型的数组 number_list，不要惊讶，<strong>在内存地址这个事情上，各种指针都是一致的，区别在于解析方式与尺寸规格</strong></p>
<p>C语言提供了一种通用性指针，void*，<strong>它仅仅关注内存地址</strong>。</p>
<p>而我们也使用了之前提到的 “桥梁&quot; void*，我们将 number_list 先转化为 void* 指针（让后来的变量仅仅关注其内存地址），再在赋值给 <code>p</code>的时候，转化为 double* 指针（表示按照 double 类型处理这一内存地址）</p>
<p>而在循环的判断中，因为我们是复制旧数组的元素，到新数组里面去，因此我们设定了一个 count_memory 变量，表示当前已经复制完成的数据量，并将其与 number_list 的内存总量对比（达到的时候，数据复制完成）</p>
<p>最后，我们指示指针p每次都要自增，这里，我们有必要提及指针自增的真正意义。</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673258843736.png" alt="1673258843736"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    ptr_plusplus.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Show the meaning of pointer plus plus
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> number <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>ptr <span style="color:#f92672">=</span> <span style="color:#f92672">&amp;</span>number;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">double</span> number_2 <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">double</span> <span style="color:#f92672">*</span>ptr_2 <span style="color:#f92672">=</span> <span style="color:#f92672">&amp;</span>number_2;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">char</span> c <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>ptr_3 <span style="color:#f92672">=</span> <span style="color:#f92672">&amp;</span>c;
</span></span><span style="display:flex;"><span>    printf(<span style="color:#e6db74">&#34;%u %u %u</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, ptr, ptr<span style="color:#f92672">++</span>, <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">int</span>));
</span></span><span style="display:flex;"><span>    printf(<span style="color:#e6db74">&#34;%u %u %u</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, ptr_2, ptr_2<span style="color:#f92672">++</span>, <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">double</span>));
</span></span><span style="display:flex;"><span>    printf(<span style="color:#e6db74">&#34;%u %u %u</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, ptr_3, ptr_3<span style="color:#f92672">++</span>, <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">char</span>));
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>这个案例体现出两件事情：</p>
<ol>
<li><strong>指针自增运算的本质就是内存地址的改变，改变量的大小取决于指针的类型（数据类型决定尺寸规格）</strong></li>
<li>自增运算将指针地址变小了，这是因为，<strong>栈地址自高向低生长</strong></li>
</ol>
<p>同时，我们也应当看到，通用指针 void* 是不能够自增运算与自减运算的，因为<strong>它只关注地址，没有确切的规格尺寸与解析方式</strong>。</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673260547185.png" alt="1673260547185"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    void_ptr.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Show a case of void*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> var <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>ptr <span style="color:#f92672">=</span> <span style="color:#f92672">&amp;</span>var;
</span></span><span style="display:flex;"><span>    printf(<span style="color:#e6db74">&#34;%u %u</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, ptr, ptr<span style="color:#f92672">++</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>在这个案例之中，我们使用两种不同的编译器（GCC 与 CLANG）对 void* 自增代码进行编译。</p>
<p>最后出现了完全不一样的结果：在 GCC 中，尽管可以通过编译，但是 void* 只改变了一个字节，而在 CLANG 中，尽管也可以通过编译，但是出现了许多警告，而最后的地址，则是完全就没有改变。</p>
<p>我们将这种情况称之为 <code>UB</code>，也就是未定义行为（结果取决于编译器的选择），在实际情况下，它很容易引发极大的问题。看人</p>
<p>指针的很多事情，就围绕着桥梁 void* 展开，接下来，让我们观察其具有的三种重要用途。</p>
<h2 id="数据类型转换">数据类型转换</h2>
<p>void* 指针可以很轻松地让我们将存储于一段内存区域的数据，以其它的方式进行解析与看待。</p>
<p>一种典型的用法就是数据的复制，如您所见。</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673266698187.png" alt="1673266698187"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    memory_copy.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Use the pointer to copy the data
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;time.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">GenerateNumberList</span>(<span style="color:#66d9ef">int</span> array[], <span style="color:#66d9ef">int</span> count)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> count; i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        array[i] <span style="color:#f92672">=</span> i;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> array[<span style="color:#ae81ff">1000</span>] <span style="color:#f92672">=</span> {};
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> array_backup[<span style="color:#ae81ff">1000</span>] <span style="color:#f92672">=</span> {};
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> count_memory <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">unsigned</span> begin, end;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    begin <span style="color:#f92672">=</span> clock();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000000</span>; i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        count_memory <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">double</span> <span style="color:#f92672">*</span>p <span style="color:#f92672">=</span> (<span style="color:#66d9ef">double</span> <span style="color:#f92672">*</span>)(<span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>)array; count_memory <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">sizeof</span>(array); p<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">*</span>(<span style="color:#66d9ef">double</span> <span style="color:#f92672">*</span>)(<span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>)((<span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>)(<span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>)array_backup <span style="color:#f92672">+</span> count_memory) <span style="color:#f92672">=</span> <span style="color:#f92672">*</span>p;
</span></span><span style="display:flex;"><span>            count_memory <span style="color:#f92672">+=</span> <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">double</span>);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    end <span style="color:#f92672">=</span> clock();
</span></span><span style="display:flex;"><span>    printf(<span style="color:#e6db74">&#34;Time: %u ms</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, (end <span style="color:#f92672">-</span> begin) <span style="color:#f92672">*</span> <span style="color:#ae81ff">1000</span> <span style="color:#f92672">/</span> CLOCKS_PER_SEC);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    begin <span style="color:#f92672">=</span> clock();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000000</span>; i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        count_memory <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>p <span style="color:#f92672">=</span> (<span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>)(<span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>)array; count_memory <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">sizeof</span>(array); p<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">*</span>(<span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>)(<span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>)((<span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>)(<span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>)array_backup <span style="color:#f92672">+</span> count_memory) <span style="color:#f92672">=</span> <span style="color:#f92672">*</span>p;
</span></span><span style="display:flex;"><span>            count_memory <span style="color:#f92672">+=</span> <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">char</span>);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    end <span style="color:#f92672">=</span> clock();
</span></span><span style="display:flex;"><span>    printf(<span style="color:#e6db74">&#34;Time: %u ms</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, (end <span style="color:#f92672">-</span> begin) <span style="color:#f92672">*</span> <span style="color:#ae81ff">1000</span> <span style="color:#f92672">/</span> CLOCKS_PER_SEC);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>在这个案例之中，我们使用两种不同类型的指针对同一段内容进行反复的复制。</p>
<p>明显看出，在同样的数据量下，double* 比 char* 快了大约 3.1 倍。</p>
<p>其根本的原因，就是在尺寸规格的不同，double 一次复制  8 个字节，而char 仅仅复制 1个字节，前者比后者多复制8倍的数据量。</p>
<h2 id="动态内存分配">动态内存分配</h2>
<p>void* 通用指针的又一大意义，就在于充当动态内存分配的桥梁。</p>
<p>从解决问题的角度上来看，动态内存分配解决的问题，在于动态变化的数据规模。</p>
<ul>
<li>自连续型数据视角</li>
</ul>
<p>一个好的案例，就是实现完成 C语言标准库函数 中的 strdup 函数，它的使用如下所示</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673308099233.png" alt="1673308099233"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    strdup.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Use the strdup function
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;string.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">char</span> string[] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Hello world&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>string_backup <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>    string_backup <span style="color:#f92672">=</span> strdup(string);
</span></span><span style="display:flex;"><span>    puts(string_backup);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>正如你所见，strdup 函数会完整的复制一段字符串到新的区域，它的实际职责，如下所示</p>
<ol>
<li>计算旧字符串的长度</li>
<li>根据旧字符串的长度，分配新内存</li>
<li>复制旧字符串到新区域中</li>
</ol>
<p>其中，我们将 步骤一 与 步骤三 以 strlen 与 memcpy 代替，专注于步骤二，进行实现</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673308513972.png" alt="1673308513972"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    my_strdup.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Use the strdup function
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;string.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdlib.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    my_strdup
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        Achieve the strdup
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Arguemnt
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        string
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">            The string want to duplicate
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Return Value
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        The new string
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">my_strdup</span>(<span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>string)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>result <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">unsigned</span> length <span style="color:#f92672">=</span> strlen(string);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#ae81ff">0</span> <span style="color:#f92672">==</span> length)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> NULL;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    result <span style="color:#f92672">=</span> (<span style="color:#66d9ef">char</span><span style="color:#f92672">*</span>)malloc(<span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">char</span>) <span style="color:#f92672">*</span> length <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (NULL <span style="color:#f92672">==</span> result)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> NULL;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    memcpy(result, string, length);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> result;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">char</span> string[] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Hello world&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>string_backup <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>    string_backup <span style="color:#f92672">=</span> my_strdup(string);
</span></span><span style="display:flex;"><span>    puts(string_backup);
</span></span><span style="display:flex;"><span>    free(string_backup);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>如你所见，我们使用 strlen 计算字符串长度（计算数据规模），用 memcpy 函数实现数据复制。</p>
<p>而关键的地方，在于中间的 malloc 函数以及之后的free函数。</p>
<p>他们是动态数据分配的基石。</p>
<p>malloc 函数会根据传入的数字分配对应尺寸的内存空间，而 free 函数则会释放由 malloc 分配的空间。</p>
<p>在分配失败的时候，malloc会返回常数 NULL，这个值一般情况下，就是 0</p>
<p>值得注意的是，<strong>如果不及时释放，会引发内存泄露问题，这会迅速耗尽系统的资源。</strong></p>
<p>同时，我们看到，在前文中，我们提到，<strong>数组是一种将同一类型进行整合的数据结构，其本质是一片连续的内存区域</strong>。</p>
<p>那么，我们能否用同样的办法，对待 malloc 分配而来的内存区域呢？</p>
<p>答案是：可以。</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673315079537.png" alt="1673315079537"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    malloc_array.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Use the malloc to create a array
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdlib.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span><span style="color:#f92672">*</span> <span style="color:#a6e22e">GenerateNumberList</span>(<span style="color:#66d9ef">int</span> count)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>result <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#ae81ff">0</span> <span style="color:#f92672">&gt;=</span> count)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> NULL;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    result <span style="color:#f92672">=</span> (<span style="color:#66d9ef">int</span><span style="color:#f92672">*</span>)malloc(count <span style="color:#f92672">*</span> <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">int</span>));
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;i <span style="color:#f92672">&lt;</span> count;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        result[i] <span style="color:#f92672">=</span> i;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> result;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">PrintNumberList</span>(<span style="color:#66d9ef">int</span> array[], <span style="color:#66d9ef">int</span> count)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;i <span style="color:#f92672">&lt;</span> count;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;%d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, array[i]);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>array <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>    array <span style="color:#f92672">=</span> GenerateNumberList(<span style="color:#ae81ff">10</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (NULL <span style="color:#f92672">==</span> array)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>    PrintNumberList(array, <span style="color:#ae81ff">10</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>在这里，我们用 malloc 根据传入的元素多少创建对应的内存区域。</p>
<p>要记住的是：malloc 分配的内存区域，就是一个一维的线性数组，而且是一个字节一个字节，因此我们<strong>在要求 malloc 分配内存的时候，不仅要考虑到元素的多少，而且要考虑到每个元素的规格尺寸</strong></p>
<p>即 <code>count * sizeof(type)</code></p>
<p>同时我们这里也体现了一个不好的习惯，就是在使用完成数组以后，没有及时释放掉分配到的内存（尽管程序退出后，这些资源被回收了）。</p>
<p>下面我们就展现这一习惯可能引发的后果。</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673315764467.png" alt="1673315764467"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    memory_run_out.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Show the result of not use free
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdlib.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>ptr <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;i <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1024</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1024</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">2</span>;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        ptr <span style="color:#f92672">=</span> malloc(<span style="color:#ae81ff">1024</span>); <span style="color:#75715e">/* 1KB */</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (NULL <span style="color:#f92672">==</span> ptr)
</span></span><span style="display:flex;"><span>            puts(<span style="color:#e6db74">&#34;Failed.&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    getchar();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>在这里，我们模拟了申请内存却不释放的后果，可以很明显的地发现，这个小程序，占据了 2.2GB 的内存。</p>
<p>在很多场景下这种逐步积累的内存泄露，往往会引发可怕的崩溃。</p>
<p>解决的办法，就是及时释放。</p>
<p>值得一提的是，malloc 分配到的内存，往往是未经初始化的内存，而如果我们希望分配到的内存是经过初始化的，可以使用 <code>calloc</code> 函数。</p>
<p><code>realloc</code> 函数用于调整内存空间的尺寸。</p>
<ul>
<li>自非连续型数据的视角</li>
</ul>
<p>非连续型数据，自我本人的观点看来，就是大量分散的小数据，他们变化频率大，需要做出的响应非常多。</p>
<p>在这里，我们举一个常见的案例。</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673316610713.png" alt="1673316610713"></p>
<p>在视频播放中，往往有一项功能被称为“A-B区段循环&quot;，这项功能的核心就是如下的功能。</p>
<ul>
<li>将设定的两点中的视频图像与音频循环输出</li>
</ul>
<p>在我们这里，我们将其简化为如下的模型</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673317855761.png" alt="1673317855761"></p>
<p>我们做出如下假定</p>
<ol>
<li>图片都是连续型数据</li>
<li>AB循环播放就是连续读取这些数据</li>
</ol>
<p>这就要求，我们对图片进行模拟。</p>
<p>由此，我们制作出如下的程序。</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673351877370.png" alt="1673351877370"></p>
<p><img src="image/%E6%8C%87%E9%92%88/1673351885396.png" alt="1673351885396"></p>
<p>由于这是一个控制台模拟程序，我们就用简单的 0-1 字符数组代替真实场景下面的像素点。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    video.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Use the link-table to solve the problem
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdlib.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;time.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> Image
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>buffer;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> width;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> height;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">struct</span> Image <span style="color:#f92672">*</span>next;
</span></span><span style="display:flex;"><span>}Image;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">Clear</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    system(<span style="color:#e6db74">&#34;clear&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">OutputImage</span>(Image <span style="color:#f92672">*</span>image)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;i <span style="color:#f92672">&lt;</span> image <span style="color:#f92672">-&gt;</span> height;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> j <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;j <span style="color:#f92672">&lt;</span> image <span style="color:#f92672">-&gt;</span> width;j<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            printf(<span style="color:#e6db74">&#34;%c &#34;</span>, <span style="color:#f92672">*</span>(image <span style="color:#f92672">-&gt;</span> buffer <span style="color:#f92672">+</span> i <span style="color:#f92672">*</span> image <span style="color:#f92672">-&gt;</span> height <span style="color:#f92672">+</span> j));
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        puts(<span style="color:#e6db74">&#34;&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>Image<span style="color:#f92672">*</span> <span style="color:#a6e22e">GenerateImage</span>(<span style="color:#66d9ef">int</span> width, <span style="color:#66d9ef">int</span> height)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Image <span style="color:#f92672">*</span>result <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> length <span style="color:#f92672">=</span> width <span style="color:#f92672">*</span> height;
</span></span><span style="display:flex;"><span>    result <span style="color:#f92672">=</span> (Image<span style="color:#f92672">*</span>)calloc(<span style="color:#ae81ff">1</span>, <span style="color:#66d9ef">sizeof</span>(Image));
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (NULL <span style="color:#f92672">==</span> result)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> NULL;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    result <span style="color:#f92672">-&gt;</span> width <span style="color:#f92672">=</span> width;
</span></span><span style="display:flex;"><span>    result <span style="color:#f92672">-&gt;</span> height <span style="color:#f92672">=</span> height;
</span></span><span style="display:flex;"><span>    result <span style="color:#f92672">-&gt;</span> buffer <span style="color:#f92672">=</span> (<span style="color:#66d9ef">char</span><span style="color:#f92672">*</span>)calloc(length, <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">char</span>));
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (NULL <span style="color:#f92672">==</span> result <span style="color:#f92672">-&gt;</span> buffer)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        free(result);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> NULL;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;i <span style="color:#f92672">&lt;</span> length;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        result <span style="color:#f92672">-&gt;</span> buffer[i] <span style="color:#f92672">=</span> rand() <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;0&#39;</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> result;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">FreeImageList</span>(Image <span style="color:#f92672">*</span>image)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Image <span style="color:#f92672">*</span>temp <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">while</span> (image)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        free(image <span style="color:#f92672">-&gt;</span> buffer);
</span></span><span style="display:flex;"><span>        free(image);
</span></span><span style="display:flex;"><span>        temp <span style="color:#f92672">=</span> image <span style="color:#f92672">-&gt;</span> next;
</span></span><span style="display:flex;"><span>        image <span style="color:#f92672">=</span> temp;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">Sleep</span>(<span style="color:#66d9ef">int</span> ms)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">register</span> <span style="color:#66d9ef">unsigned</span> begin <span style="color:#f92672">=</span> clock();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">while</span> ((clock() <span style="color:#f92672">-</span> begin) <span style="color:#f92672">*</span> <span style="color:#ae81ff">1000</span> <span style="color:#f92672">/</span> CLOCKS_PER_SEC <span style="color:#f92672">&lt;</span> ms)
</span></span><span style="display:flex;"><span>        ;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Image <span style="color:#f92672">*</span>first <span style="color:#f92672">=</span> NULL, <span style="color:#f92672">*</span>last <span style="color:#f92672">=</span> NULL, <span style="color:#f92672">*</span>temp <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>    first <span style="color:#f92672">=</span> (Image<span style="color:#f92672">*</span>)calloc(<span style="color:#ae81ff">1</span>, <span style="color:#66d9ef">sizeof</span>(Image));
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (NULL <span style="color:#f92672">==</span> first)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>    first <span style="color:#f92672">=</span> GenerateImage(<span style="color:#ae81ff">10</span>, <span style="color:#ae81ff">10</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (NULL <span style="color:#f92672">==</span> first)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    last <span style="color:#f92672">=</span> first;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;i <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">24</span>;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        temp <span style="color:#f92672">=</span> GenerateImage(<span style="color:#ae81ff">10</span>, <span style="color:#ae81ff">10</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (NULL <span style="color:#f92672">==</span> temp)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            FreeImageList(first);
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        last <span style="color:#f92672">-&gt;</span> next <span style="color:#f92672">=</span> temp;
</span></span><span style="display:flex;"><span>        last <span style="color:#f92672">=</span> temp;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">while</span> (<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        temp <span style="color:#f92672">=</span> first;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;i <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">24</span>;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            Clear();
</span></span><span style="display:flex;"><span>            OutputImage(temp);
</span></span><span style="display:flex;"><span>            temp <span style="color:#f92672">=</span> temp <span style="color:#f92672">-&gt;</span> next;
</span></span><span style="display:flex;"><span>            Sleep(<span style="color:#ae81ff">30</span>);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    FreeImageList(first);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>如您所见，这个程序有些复杂，下面，让我们逐一分析他们。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> Image
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>buffer;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> width;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> height;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">struct</span> Image <span style="color:#f92672">*</span>next;
</span></span><span style="display:flex;"><span>}Image;
</span></span></code></pre></div><p>Image 结构定义每一帧的图像，并设计了 next 指针使其可以作为“链表&quot;使用。</p>
<p>“链表&quot;可以被视为数组的一种，但是它的内存地址并不连续，这是因为，链表的每一个节点，都是动态申请内存的。</p>
<p>我们将链表的基本流程分析如下：</p>
<p>假定有三个变量 first，last，temp 用于描述一个链表结构，分别代表 第一个元素，最后一个元素，临时储存。</p>
<ol>
<li>第一步：判断第一个元素 first 的状态
<ol>
<li>假如第一个元素 first 处于 NULL 状态（链表没有任何元素），那么我们会为这个元素申请内存空间，并将最后一个元素 last 设置为第一个元素，结束整个流程</li>
<li>否则，进入下一步</li>
</ol>
</li>
<li>第二步：申请一个元素的内存空间
<ol>
<li>申请成功，则将其保存于 temp 中</li>
<li>否则，失败</li>
</ol>
</li>
<li>第三步：将 last 设定为新元素的地址，也就是用 temp 的值填充 last
<ol>
<li>但是在这之前，我们需要将当下最后元素的“下一个节点&quot;（next）设定为 temp（新元素）</li>
</ol>
</li>
</ol>
<p>这便是链表的基本流程。</p>
<p>而使用链表的流程也非常简单，只需要从第一个元素开始，依据 next 中的值，一直循环到最后一个节点，就可以完成流程。</p>
<p>我们的 OutputImage，FreeImageList都是这个逻辑。</p>
<p>而 GenerateImage 则是做了两个工作，申请内存空间，填充数据。</p>
<p>可以发现，申请结构体的内存空间与一般类型没有什么不一样，这是因为，<strong>结构体的本质就是数据类型的类型，用于描述二进制数据的尺寸、规格、储存方式</strong></p>
<p>所以我们完全可以用 <code>malloc(sizeof(struct struct_name))</code> 的方式处理他们。</p>
<h2 id="动态数据处理">动态数据处理</h2>
<p>指针除了用于能够充当内存数据描述的桥梁，以及进行动态内存分配以应对不断变化的数据之外，还能够充当动态数据处理（函数指针）的桥梁 。</p>
<p>在这里，我们有必要指出：C语言中函数就是对于重复性代码的封装，其自身也具有对应的地址（指令起始地址）。</p>
<p>而指针的核心也是地址，那么，我们当然可以将其应用到函数上。</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673357405643.png" alt="1673357405643"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    function_pointer.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Use the function pointer to solve the problem
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">Add</span>(<span style="color:#66d9ef">int</span> number_1, <span style="color:#66d9ef">int</span> number_2)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> number_1 <span style="color:#f92672">+</span> number_2;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> (<span style="color:#f92672">*</span>function)(<span style="color:#66d9ef">int</span>, <span style="color:#66d9ef">int</span>) <span style="color:#f92672">=</span> Add;
</span></span><span style="display:flex;"><span>    printf(<span style="color:#e6db74">&#34;%u %u %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, function, Add, function(<span style="color:#ae81ff">256</span>, <span style="color:#ae81ff">256</span>));
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>在这个案例之中，我们定义了一个函数指针，并让他指向了函数 Add。</p>
<p>同时，我们输出了函数指针 function 所储存的地址 与 函数 Add 的地址，并用 function 指针处理数据。</p>
<p>这就说明在C语言函数调用中，函数名本身也是一个指针，指向指令所起始的地址，而参数列表，则承担传入数据的责任。</p>
<p>现在，让我们看第二个案例</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673357781626.png" alt="1673357781626"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    function_pointer_second.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Use the function pointer to solve the problem
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">Add</span>(<span style="color:#66d9ef">int</span> number_1, <span style="color:#66d9ef">int</span> number_2)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    printf(<span style="color:#e6db74">&#34;%d %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, number_1, number_2);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> number_1 <span style="color:#f92672">+</span> number_2;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> (<span style="color:#f92672">*</span>function)(<span style="color:#66d9ef">char</span>, <span style="color:#66d9ef">char</span>) <span style="color:#f92672">=</span> Add;
</span></span><span style="display:flex;"><span>    printf(<span style="color:#e6db74">&#34;%u %u %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, function, Add, function(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>));
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>在这个案例中，我们故意让函数指针的参数列表与原函数不匹配，在这种情况下，函数的参数传递会按照函数指针所设定的参数列表年进行传递。</p>
<p>表面上没有出现问题，是因为(1, 1)没有超出 char 的尺寸规格</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673358131704.png" alt="1673358131704"></p>
<p>稍加修订，就可以看出问题。</p>
<p>在C语言中，提供了一个函数，叫做 qsort，它的核心作用，就是排序。</p>
<p><img src="image/%E6%8C%87%E9%92%88/1673359681785.png" alt="1673359681785"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    qsort.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Use the qsort to solve the problem
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    BeginnerC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdlib.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">cmp</span>(<span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>element_1, <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>element_2)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#f92672">*</span>(<span style="color:#66d9ef">int</span><span style="color:#f92672">*</span>)element_1 <span style="color:#f92672">&gt;</span> <span style="color:#f92672">*</span>(<span style="color:#66d9ef">int</span><span style="color:#f92672">*</span>)element_2;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> array[] <span style="color:#f92672">=</span> {<span style="color:#ae81ff">8</span>, <span style="color:#ae81ff">9</span>, <span style="color:#ae81ff">6</span>, <span style="color:#ae81ff">6</span>, <span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">7</span>, <span style="color:#ae81ff">5</span>};
</span></span><span style="display:flex;"><span>    qsort(array, <span style="color:#66d9ef">sizeof</span>(array) <span style="color:#f92672">/</span> <span style="color:#66d9ef">sizeof</span>(array[<span style="color:#ae81ff">0</span>]), <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">int</span>), cmp);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;i <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">sizeof</span>(array) <span style="color:#f92672">/</span> <span style="color:#66d9ef">sizeof</span>(array[<span style="color:#ae81ff">0</span>]);i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        printf(<span style="color:#e6db74">&#34;%d &#34;</span>, array[i]);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    puts(<span style="color:#e6db74">&#34;&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>如您所见，qsort 函数要求我们提供函数的地址，并让我们在函数中自己设定比较规则（通过通用指针 void* 实现对各种类型的兼容)，从而实现“通用类型排序&quot;。</p>

        </div>

        <div class="row middle-xs">
          <div class="col-xs-12">
            
            <div class="post-tags">
              <a href="/tags/c%E8%AF%AD%E8%A8%80%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97/">
                C语言入门指南
              </a>
            </div>
            
            <div class="post-tags">
              <a href="/tags/c%E8%AF%AD%E8%A8%80/">
                C语言
              </a>
            </div>
            
            <div class="post-tags">
              <a href="/tags/%E4%BF%A1%E6%81%AF%E7%AE%A1%E7%90%86%E5%AE%9E%E9%AA%8C%E5%AE%A4/">
                信息管理实验室
              </a>
            </div>
            
          </div>
        </div>
        
          <div class="row">
            <div class="col-xs-12">
              
            </div>
          </div>

          

<div class="related-content">
  <h3>Related Posts</h3>
  <ul>
    
    <li><a href="/posts/%E7%A4%BE%E5%8C%BA%E4%B9%A6%E7%B1%8D/c%E8%AF%AD%E8%A8%80%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97/%E5%85%A5%E9%97%A8c%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84%E9%80%BB%E8%BE%91%E4%B8%8E%E5%BE%AA%E7%8E%AF/">入门：C语言中的逻辑与循环</a></li>
    
    <li><a href="/posts/%E7%A4%BE%E5%8C%BA%E4%B9%A6%E7%B1%8D/c%E8%AF%AD%E8%A8%80%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97/%E5%85%A5%E9%97%A8%E5%87%BD%E6%95%B0/">入门：函数</a></li>
    
    <li><a href="/posts/%E7%A4%BE%E5%8C%BA%E4%B9%A6%E7%B1%8D/c%E8%AF%AD%E8%A8%80%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97/%E5%85%A5%E9%97%A8%E5%8F%98%E9%87%8F/">入门：变量</a></li>
    
  </ul>

</div>


          
          
          <div style="height: 50px;"></div>
          
        

        <div class="site-footer">
  
  
</div>

      </div>
    </div>
  </article>

  

<script>
  
  
    
    
  
</script>

  

</body>

</html>